home *** CD-ROM | disk | FTP | other *** search
- #define XDME
- /******************************************************************************
-
- MODULE
- AVL.c
-
- DESCRIPTION
- simple implementation for (recursive) AVL-trees
- this code can be used for an Amiga(c) shared library
-
- NOTES
-
- if You wanna use that code as a non-shared library
- You might have to modify some "#define"s below; also
- it might be useful to re"#define" A0,A1,A2,D0 and PRE.
- (see below (search for LIB_TYPE))
-
- compile w/ #define ANY_DEBUG to get basic error-checking
- #define AVL_DEBUG to get almost full-featured error-checking
- in either case You must initialize an function-var called
- extern void (*error)(char*, char*, char*);
- which displays our errors;
-
- BUGS
- that implementation on AVL - as is - does not
- create any errormessages; user must make sure,
- not to mess up w/ the trees, nor using two nodes
- of the same name;
-
- TODO
- maybe certain Header structures,
- to support other comparison functions
- and error functions
-
- EXAMPLES
- for AVL-trees there are soooo many examples in other pgms
-
- SEE ALSO
-
- INDEX
-
- HISTORY
- 05-07-93 b_noll created
- 12-07-93 b_noll added ScanTree, FreeTree
- 21-07-93 b_noll changed switch()'s to if()'s
- 22-07-93 b_noll disabled all error-calls
- 07-10-93 b_noll [re]activated LSON/RSON/NAME/BAL-Macros
- 07-11-93 b_noll fixed bug in rem_rek (there were no reports)
- 12-05-94 b_noll joined xdme-verion and lib-version
- 04-09-94 b_noll BUGFIX in AVL_balance
- 16-11-94 b_noll strcmp replaced by external compare function
- $Date: 1994/09/04 17:49:50 $ last update
-
- ******************************************************************************/
-
- /**************************************
- Includes
- **************************************/
-
- /* we do not import AVL.h since we did hide tn_Balance from the user there */
- #ifndef AVL_H
- /* #include <AVL.h> */
- /* #define AVL_H */
- #endif /* AVL_H */
-
- #ifndef EXEC_TYPES_H
- #include <exec/types.h>
- #endif /* EXEC_TYPES_H */
-
- /**************************************
- Global Variables
- **************************************/
-
- #ifdef XDME
- #define ERROR(x,y,z) error(x,y,z)
- extern void error(const char*, ...);
- #define ANY_DEBUG 1
- #else
- #define ERROR(x,y,z) if (error) (*error)(x,y,z)
- void (*error)(char const *, char const *, char const *) = NULL;
- #endif
-
-
- /**************************************
- Internal Defines & Structures
- **************************************/
-
- #ifndef AVL_H
- /* redefine it here as we did comment out tn_Balance in AVL.h */
- struct TreeNode {
- struct TreeNode * tn_Left;
- struct TreeNode * tn_Right;
- UBYTE tn_Type;
- BYTE tn_Balance; /* !PRIVATE! for AVL - do not use it! */
- }; /* struct TreeNode */
- #endif /* !AVL_H */
-
- /**************************************
- Internal Variables
- **************************************/
-
- /* none */
-
- /**************************************
- Internal Prototypes
- **************************************/
-
- /* static int AVL_rem_rek (struct TreeNode**, struct TreeNode*, int (*compare)(APTR, APTR)); */
- /* static int AVL_add_rek (struct TreeNode**, struct TreeNode*, int (*compare)(APTR, APTR)); */
- /* static int AVL_balance (struct TreeNode**); */
-
- /**************************************
- Macros
- **************************************/
-
- /**************************************************
- **
- ** !! LIB_TYPE !!
- **
- ** Change the following lines to switch
- ** between a shared-library and a link-library
- ** #if 1 -> SHARED
- ** #if 0 ->LINK
- **
- **************************************************/
- #if 0
- /* SHARED LIB: */
- #define AVL_Find LIBAVL_Find
- #define AVL_Append LIBAVL_Append
- #define AVL_Remove LIBAVL_Remove
- #define AVL_FreeTree LIBAVL_FreeTree
- #define AVL_ScanTree LIBAVL_ScanTree
- #define PRE __asm __saveds
- #define A0(x) register __a0 x
- #define A1(x) register __a1 x
- #define A2(x) register __a2 x
- #define D0(x) register __d0 x
- #else
- /* LINK LIB: */
- #define PRE
- #define A0(x) x
- #define A1(x) x
- #define A2(x) x
- #define D0(x) x
- #endif
- /*************************************************/
-
- #define INC(x) ++(x)
- #define DEC(x) --(x)
-
- #define RSON(x) (x)->tn_Right
- #define LSON(x) (x)->tn_Left
- #define BLNC(x) (x)->tn_Balance
-
- #define BAL(x) BLNC(x)
-
- #define AVL_SCAN_PRAEFIX 0
- #define AVL_SCAN_INFIX 1
- #define AVL_SCAN_POSTFIX -1
-
- /**************************************
- Implementation
- **************************************/
-
- #ifdef ANY_DEBUG
- const char* AVL_errdisp1 = "AVL:\n%s!\n";
- const char* AVL_errdisp2 = "AVL:\n%s %s!\n";
-
- const char* AVL_err_notree = "without a tree";
- const char* AVL_err_cotree = "with a corrupt tree";
- const char* AVL_err_multi = "Can not manage multiple nodes\nof same name in one tree";
-
- const char* AVL_err_balan = "called Balance";
- const char* AVL_err_rem = "called Remove";
- const char* AVL_err_add = "called Append";
- const char* AVL_err_find = "called Find";
- const char* AVL_err_free = "called FreeTree";
- const char* AVL_err_scan = "called ScanTree";
- #endif /* ANY_DEBUG */
-
-
- /*****************************************************************************
-
- NAME
- AVL_balance
-
- PARAMETER
- struct TreeNode** t;
-
- RESULT
- the balance of the new root (? really)
-
- RETURN
- int;
-
- DESCRIPTION
- do a local rebalance if the current node's
- balance is worse than +/- 1
-
- the function is used by AVL_add_rek and
- by AVL_rem_rek on the way back from a
- addition/deletion;
-
- NOTES
- that rebalance affect only up to three nodes;
-
- the function might have been done in a more
- effective way - but I wanna be able to read it
- also in 2 weeks.
-
- BUGS
- none known
-
- EXAMPLES
- why - its hidden
-
- SEE ALSO
- AVL_add_rek, AVL_rem_rek
-
- INTERNALS
- verschachtelte case-construkte,
- um alle normalen Faelle abzudecken,
- die bei AVL_Append und AVL_Remove
- auftreten koennen;
- den Rest habe in mir mit Bildchen
- klargemacht.
-
- Hier mehr zu schreiben hat m.E. keinen
- Sinn, das geht besser mit Papier und Bleistift;
-
- HISTORY
- 05-07-93 b_noll created
-
- ******************************************************************************/
- static
- int AVL_balance (struct TreeNode** t)
- {
- struct TreeNode* ot = *t;
- struct TreeNode* lt = LSON(ot);
- struct TreeNode* rt = RSON(ot);
- char b = BAL(ot);
-
- if (!ot) {
- ERROR (AVL_errdisp2, AVL_err_balan, "with NULL ptr");
- return 0;
- }
-
-
- /* D(bug("AVL:balancing...")); */
-
- switch (b) {
-
- #ifdef AVL_DEBUG
- case -1:
- case 0:
- case +1:
- ERROR (AVL_errdisp2, AVL_err_balan, "without need");
- return (b);
- #endif /* AVL_DEBUG */
-
- case +2:
- b = BAL(lt);
- switch (b) {
- case -1:
- /* D(bug("LR")); */
- rt = RSON(lt);
- *t = rt;
- LSON(ot) = RSON(rt);
- RSON(lt) = LSON(rt);
- LSON(rt) = lt;
- RSON(rt) = ot;
-
-
- b = BAL(rt);
- BAL(rt) = 0;
- BAL(lt) = (1-b)/2; /* -:1 0:0 +:0 */
- BAL(ot) = -(1+b)/2; /* 0 0 -1 */
-
- return 0;
-
- case 0:
- case +1: /* LL */
- /* D(bug("LL")); */
- *t = lt;
- LSON(ot) = RSON(lt);
- RSON(lt) = ot;
-
- BAL(ot) = -(b-1); /* 0:+1; +1:0 */
- BAL(lt) = +(b-1); /* -1; 0 */
-
- return b-1;
-
- #ifdef AVL_DEBUG
- default:
- ERROR ( AVL_errdisp2, AVL_err_balan, AVL_err_cotree);
- #endif /* AVL_DEBUG */
- } /* switch */
-
- break;
-
- case -2:
- b = BAL(rt);
- switch (b) {
- case +1:
- /* D(bug("RL")); */
- lt = LSON(rt);
- *t = lt;
- RSON(ot) = LSON(lt);
- LSON(rt) = RSON(lt);
- LSON(lt) = ot;
- RSON(lt) = rt;
-
- b = BAL(lt);
- BAL(lt) = 0;
- BAL(rt) = -(1+b)/2; /* -:0 0:0 +: */
- BAL(ot) = (1-b)/2; /* 1 0 */
- /* D(bug("b== %d\n",b)); */
-
- return 0;
-
- case 0:
- case -1: /* RR */
-
- /* D(bug("RR")); */
- *t = rt;
- RSON(ot) = LSON(rt);
- LSON(rt) = ot;
-
- /* Vorzeichen ??? */
- BAL(ot) = -(b+1); /* 0:-1; -1:0 */
- BAL(rt) = +(b+1); /* +1; 0 */
- /* D(bug("ot%d rt%d\n", -(b+1), (b+1))); */
- return -(b-1);
-
- #ifdef AVL_DEBUG
- default:
- ERROR ( AVL_errdisp2, AVL_err_balan, AVL_err_cotree);
- #endif /* AVL_DEBUG */
- } /* switch */
- break;
-
- #ifdef AVL_DEBUG
- default:
- ERROR ( AVL_errdisp2, AVL_err_balan, AVL_err_cotree);
- #endif /* AVL_DEBUG */
- } /* switch */
-
- return 0;
- } /* AVL_balance */
-
-
-
- /*****************************************************************************
-
- NAME
- AVL_swap_best_right
-
- PARAMETER
- struct TreeNode** swapme;
-
- RESULT
- swapping was necessary and done
-
- RETURN
- BOOL;
-
- DESCRIPTION
- swap the current node (swapme) with the
- leftmost follower/son of its right son
-
- NOTES
- swapping with the rightmost follower of its left son
- would have a similar effect;
-
- perhaps we should first check for a better balance to
- decide which one to use (we have to rename the function then)
-
- BUGS
- none known
-
- EXAMPLES
- why - its hidden
-
- SEE ALSO
- AVL_rem_rek
-
- INTERNALS
- die function ist in 2 Teile zerlegbar:
- die Suche nach dem "optimalen" Nachfolger
- danach das Vertauschen dieses Nachfolgers
- mit dem Root.
-
- HISTORY
- 05-07-93 b_noll created
-
- ******************************************************************************/
- static
- BOOL AVL_swap_best_right (struct TreeNode** swapme)
- {
- struct TreeNode* root = *swapme;
- struct TreeNode* curr = root;
- struct TreeNode* prev = NULL;
- struct TreeNode* z;
-
- /* D(bug("AVL:swappin' ...")); */
-
- { /* search the mostleft node of the right son */
- if ((curr = RSON(root)) == NULL) {
- return FALSE;
- } /* if */
-
-
- while ((z = LSON(curr))) {
- prev = curr;
- curr = z;
- } /* while */
- }
-
- { /* swap our node and the leftmost right son */
- z = RSON(curr);
- if (prev) {
- LSON(prev) = root;
- RSON(curr) = RSON(root);
- } else {
- RSON(curr) = root;
- } /* if */
-
- RSON(root) = z;
-
- *swapme = curr;
- LSON(curr) = LSON(root);
- LSON(root) = NULL;
- }
-
-
- { /* swap the balances, too! */
- char bal = BAL(root);
- BAL(root) = BAL(curr);
- BAL(curr) = bal;
- }
-
- return TRUE;
- } /* AVL_swap_best_right */
-
-
-
- /*****************************************************************************
-
- NAME
- AVL_rem_rek
-
- PARAMETER
- struct TreeNode** tree;
- struct TreeNode* obj;
- int (*compare)(A0(APTR),A1(APTR));
-
- RESULT
- The Tree's change of height
-
- RETURN
- int;
-
- DESCRIPTION
- hidden part of AVL_Remove
-
- NOTES
- no security checks involved;
-
- BUGS
- use of 2 nodes w/ the same Id will
- lead into trouble
-
- EXAMPLES
- why - its hidden
-
- SEE ALSO
- AVL_Remove
-
- INTERNALS
- the deletion is done recursively
-
- zunaechst suchen wir nach dem Knoten,
- den wir herausloesen wollen (nur ueber
- check!) bringen den dann an eine
- Position, wo wir loeschen koennen
- und knipsen ihn dort heraus;
- auf dem Rueckweg wird der Baum bei Bedarf
- rebalaniert
-
- HISTORY
- 05-07-93 b_noll created
- 21-07-93 b_noll switch(strcmp) -> if(diff) to handle w/ SAS
- 16-11-94 b_noll strcmp replaced by external compare function
-
- ******************************************************************************/
- static
- int AVL_rem_rek (struct TreeNode** tree, struct TreeNode* obj, int (*compare)(A0(APTR),A1(APTR)))
- {
-
- struct TreeNode* n = *tree;
- int diff;
-
- if (!n) {
- #ifdef ANY_DEBUG
- ERROR ( AVL_errdisp1, "Can't remove non-added node", NULL);
- #endif /* ANY_DEBUG */
- return 0;
- } /* if */
-
- if ((diff = compare(obj,n)) == 0) {
- if (n != obj) {
- #ifdef ANY_DEBUG
- ERROR ( AVL_errdisp1, AVL_err_multi, NULL);
- #endif /* ANY_DEBUG */
- return 0;
- } /* if */
-
- if (AVL_swap_best_right(tree)) { /* noch nich' am boden */
- n = *tree;
- goto remright; /* ab hier koennte es beschleunigt werden */
- } else { /* schon am rand - abschneiden */
- *tree = LSON(n); /* PATCH_NULL BUGFIX [07 Nov 1993] : Right <-> Left */
- return 1;
- } /* if am rand */
-
- } else if (diff > 0) {
- remright:
- if ( AVL_rem_rek(&RSON(n), obj, compare) ) {
- INC(BAL(n));
- if (BAL(n) == 2) {
- AVL_balance(tree);
- } /* if */
- return !BAL(*tree);
- } /* if */
- return 0;
-
- } else {
- if ( AVL_rem_rek(&LSON(n), obj, compare) ) {
- DEC(BAL(n));
- if (BAL(n) == -2) {
- AVL_balance(tree);
- } /* if */
- return !BAL(*tree);
- } /* if */
- return 0;
-
- } /* if */
- } /* AVL_rem_rek */
-
-
- /*****************************************************************************
-
- NAME
- AVL_add_rek
-
- PARAMETER
- struct TreeNode** tree;
- struct TreeNode* obj;
- int (*compare)(A0(APTR),A1(APTR));
-
- RESULT
- The Tree's change of height
-
- RETURN
- int;
-
- DESCRIPTION
- hidden part of AVL_Append
-
- NOTES
- no security checks involved;
-
- BUGS
- none known
-
- EXAMPLES
- why - its hidden
-
- SEE ALSO
- AVL_Append
-
- INTERNALS
- the addition is done recursively
-
- wir gehen solange nach unten, bis
- wir auf ein NIL-kind stossen und
- haengen unseren Node dorthin;
- auf dem Rueckweg wird der Baum bei Bedarf
- rebalaniert
-
- HISTORY
- 05-07-93 b_noll created
- 21-07-93 b_noll switch(strcmp) -> if(diff) to handle w/ SAS
- 16-11-94 b_noll strcmp replaced by external compare function
-
- ******************************************************************************/
- static
- int AVL_add_rek (struct TreeNode** tree, struct TreeNode* obj, int (*compare)(A0(APTR),A1(APTR)))
- {
- struct TreeNode* n = *tree;
- int diff;
-
- if (!n) {
- *tree = obj;
- RSON(obj) = NULL;
- LSON(obj) = NULL;
- BAL(obj) = 0;
- return 1;
- } /* if */
-
- if ((diff = compare(obj, n)) == 0) {
- #ifdef ANY_DEBUG
- ERROR ( AVL_errdisp1, AVL_err_multi, NULL);
- #endif /* ANY_DEBUG */
- return 0;
-
- } else if (diff > 0) {
- if (AVL_add_rek(&RSON(n), obj, compare)) {
- DEC(BAL(n));
- if (BAL(n) == -2) {
- AVL_balance(tree);
- } else {
- return BAL(n);
- } /* if */
- } /* if */
- return 0;
-
- } else {
- if (AVL_add_rek(&LSON(n), obj, compare)) {
- INC(BAL(n));
- if (BAL(n) == 2) {
- AVL_balance(tree);
- } else {
- return BAL(n);
- } /* if */
- } /* if */
- return 0;
-
- } /* if */
- } /* AVL_add_rek */
-
-
-
- /*****************************************************************************
-
- NAME
- AVL_Find
-
- PARAMETER
- A0( struct TreeNode** tree );
- A1( APTR userdata );
- A2( int (*check)(A0(APTR),A1(APTR)));
-
- RESULT
- the treenode, that matches name - if exists
-
- RETURN
- PRE struct TreeNode*;
-
- DESCRIPTION
- search for name in the tree
-
- NOTES
- check() must return 0 on match, <0 and >0 like
- compare in the insert/remove functions ...
- its 1st arg is a TreeNode, the 2nd is userdata
-
- ** Be Aware - You must give the Tree's ADDRESS **
- (that would not have been necessary, here, but
- so I can show a little bit more consistency,
- since AVL_Append and AVL_Remove do need it)
-
- BUGS
- none known
-
- EXAMPLES
-
- SEE ALSO
- AVL_Append, AVL_Remove
-
- INTERNALS
- search is done iteratively
-
- HISTORY
- 05-07-93 b_noll created
-
- ******************************************************************************/
-
- PRE struct TreeNode* AVL_Find (A0( struct TreeNode** tree ), A1( APTR userdata ), A2( int (*check)(A0(APTR),A1(APTR))))
- {
- int diff;
- struct TreeNode* n;
-
- if (!tree) {
- #ifdef AVL_DEBUG
- ERROR ( AVL_errdisp2, AVL_err_find, AVL_err_notree);
- #endif /* AVL_DEBUG */
- return NULL;
- } /* if */
-
- n = *tree;
-
- while ((n != NULL) && (diff = check(n,userdata))) {
- if (diff > 0) {
- n = RSON(n);
- } else {
- n = LSON(n);
- } /* if */
- } /* while */
-
- return n;
- } /* AVL_Find */
-
-
-
- /*****************************************************************************
-
- NAME
- AVL_Remove
-
- PARAMETER
- A0( struct TreeNode** tree );
- A1( struct TreeNode* remove );
- A2( int (*compare)(A0(APTR),A1(APTR)));
-
- RESULT
- *tree == the tree after Deleting the obsolete node
-
- RETURN
- PRE struct TreeNode*;
-
- DESCRIPTION
- Remove a node from an avl-tree; the right
- position is searched with compare()
-
- NOTES
- U first have to search for the node which
- is to be deleted e.g.:
- AVL_Rem(&tree, FindTreeNode(&tree, name ));
-
- ** Be Aware - You must give the Tree's ADDRESS **
-
- BUGS
- none known
-
- EXAMPLES
-
- SEE ALSO
- AVL_Find, AVL_Append, AVL_rem_rek
-
- INTERNALS
- the deletion is actually done by AVL_rem_rek
- AVL_Remove is only something like a security-
- interface
-
- HISTORY
- 05-07-93 b_noll created
- 16-11-94 b_noll added compare
-
- ******************************************************************************/
-
- PRE struct TreeNode* AVL_Remove (A0( struct TreeNode** tree ), A1( struct TreeNode* remove ), A2( int (*compare)(A0(APTR),A1(APTR))))
- {
- if (!tree) {
- #ifdef AVL_DEBUG
- ERROR ( AVL_errdisp2, AVL_err_rem, AVL_err_notree);
- #endif /* AVL_DEBUG */
- return NULL;
- } /* if */
-
- if (!(*tree))
- return NULL;
-
- if (remove)
- AVL_rem_rek (tree, remove, compare);
-
- return *tree;
- } /* AVL_Remove */
-
-
-
-
- /*****************************************************************************
-
- NAME
- AVL_Append
-
- PARAMETER
- A0( struct TreeNode** tree );
- A1( struct TreeNode* new );
- A2( int (*compare)(A0(APTR),A1(APTR)));
-
- RESULT
- *tree == the tree after Appending the new node
-
- RETURN
- PRE struct TreeNode*;
-
- DESCRIPTION
- Append a new node to an avl-tree; the right
- position is calculated with compare()
-
- NOTES
- U cannot define two nodes with the same
- name in one tree
-
- ** Be Aware - You must give the Tree's ADDRESS **
-
- BUGS
- none known
-
- EXAMPLES
-
- SEE ALSO
- AVL_Remove, AVL_add_rek
-
- INTERNALS
- the Addition is actually done by AVL_add_rek
- AVL_Append is only something like a security-
- interface
-
- HISTORY
- 05-07-93 b_noll created
- 16-11-94 b_noll added compare
-
- ******************************************************************************/
-
- PRE struct TreeNode* AVL_Append (A0( struct TreeNode** tree ), A1( struct TreeNode* new ), A2( int (*compare)(A0(APTR),A1(APTR))))
- {
- if (!tree) {
- #ifdef AVL_DEBUG
- ERROR ( AVL_errdisp2, AVL_err_add, AVL_err_notree);
- #endif /* AVL_DEBUG */
- return NULL;
- } /* if */
-
- if (new)
- AVL_add_rek (tree, new, compare);
-
- return *tree;
- } /* AVL_Append */
-
-
-
- /*****************************************************************************
-
- NAME
- AVL_FreeTree
-
- PARAMETER
- A0( struct TreeNode** tree );
- A1( void (*freefunc)(A0( APTR )) );
-
- RESULT
- -/-
-
- RETURN
- PRE void
-
- DESCRIPTION
- free all entries of a certain tree;
-
- NOTES
- ** Be Aware - You must give the Tree's ADDRESS **
-
- ** Be Aware - You must not delete a partial tree,
- but only whole trees **
-
- BUGS
- none known
-
- EXAMPLES
-
- SEE ALSO
-
- INTERNALS
- the tree is completely deleted, without respect to
- any balance; we expect to call that function only on
- root-nodes;
-
- HISTORY
- 12-07-93 b_noll created
-
- ******************************************************************************/
-
- PRE void AVL_FreeTree (A0( struct TreeNode** tree ), A1( void (*freefunc)(A0( APTR )) ))
- {
- if (tree) {
- if (*tree) {
- AVL_FreeTree(&(LSON(*tree)), freefunc);
- AVL_FreeTree(&(RSON(*tree)), freefunc);
- (*freefunc) (*tree);
- *tree = NULL;
- } /* if */
- #ifdef AVL_DEBUG
- } else {
- ERROR ( AVL_errdisp2, AVL_err_free, AVL_err_notree);
- #endif /* AVL_DEBUG */
- } /* if */
- } /* AVL_FreeTree */
-
-
-
- /*****************************************************************************
-
- NAME
- AVL_ScanTree
-
- PARAMETER
- A0( struct TreeNode** tree );
- A1( void (*scanfunc)(A0( APTR )) );
- D0( char mode );
-
- RESULT
- -/-
-
- RETURN
- PRE void
-
- DESCRIPTION
- call a certain function on all nodes of a certain tree
-
- NOTES
- ** Be Aware - You must give the Tree's ADDRESS **
-
- BUGS
-
- EXAMPLES
-
- SEE ALSO
-
- INTERNALS
-
- HISTORY
- 12-07-93 b_noll created
-
- ******************************************************************************/
-
- PRE void AVL_ScanTree (A0( struct TreeNode** tree ), A1( void (*scanfunc)(A0( APTR )) ), D0( char mode ))
- {
- if (tree) {
- if (*tree) {
- if (mode == AVL_SCAN_PRAEFIX) (*scanfunc) (*tree);
- AVL_ScanTree(&(LSON(*tree)), scanfunc, mode);
- if (mode == AVL_SCAN_INFIX ) (*scanfunc) (*tree);
- AVL_ScanTree(&(RSON(*tree)), scanfunc, mode);
- if (mode == AVL_SCAN_POSTFIX) (*scanfunc) (*tree);
- } /* if */
- #ifdef AVL_DEBUG
- } else {
- ERROR ( AVL_errdisp2, AVL_err_scan, AVL_err_notree);
- #endif /* AVL_DEBUG */
- } /* if */
- } /* AVL_ScanTree */
-
-
-
-
- /******************************************************************************
- ***** END AVL.c
- ******************************************************************************/
-